This patch fixes an error booting 32bit vista on VMX.
authorSteven Hand <steven@xensource.com>
Fri, 22 Sep 2006 11:27:28 +0000 (12:27 +0100)
committerSteven Hand <steven@xensource.com>
Fri, 22 Sep 2006 11:27:28 +0000 (12:27 +0100)
The shadow code uses hvm_get_guest_ctrl_reg(v, 4) to test whether
PAE is enabled or not.  But it is not always right if the hypervisor
calls hvm_get_guest_ctrl_reg(v, 4) between vmxassist_invoke and
vmxassist_restore

The patch uses the d->arch.hvm_vmx.cpu_state to test if the PAE is
enabled.

Also update SVM code to use the new 'pae_enabled' hvm func.

Signed-off-by: Xiaohui Xin <xiaohui.xin@intel.com>
Signed-off-by: Steven Hand <steven@xensource.com>
xen/arch/x86/hvm/svm/svm.c
xen/arch/x86/hvm/vmx/vmx.c
xen/arch/x86/mm/shadow/common.c
xen/include/asm-x86/hvm/hvm.h
xen/include/asm-x86/hvm/vmx/vmcs.h
xen/include/asm-x86/hvm/vmx/vmx.h

index 02e3316dcfa8cb996cd584702033133f3ca44dc7..da0e1a9d2fe5cfa0e2ed7888c535d1e747fe2a67 100644 (file)
@@ -259,6 +259,17 @@ static int svm_paging_enabled(struct vcpu *v)
     return (cr0 & X86_CR0_PE) && (cr0 & X86_CR0_PG);
 }
 
+static int svm_pae_enabled(struct vcpu *v)
+{
+    unsigned long cr4;
+
+    if(!svm_paging_enabled(v))
+        return 0;
+
+    cr4 = v->arch.hvm_svm.cpu_shadow_cr4;
+
+    return (cr4 & X86_CR4_PAE);
+}
 
 #define IS_CANO_ADDRESS(add) 1
 
@@ -865,6 +876,7 @@ int start_svm(void)
     hvm_funcs.realmode = svm_realmode;
     hvm_funcs.paging_enabled = svm_paging_enabled;
     hvm_funcs.long_mode_enabled = svm_long_mode_enabled;
+    hvm_funcs.pae_enabled = svm_pae_enabled;
     hvm_funcs.guest_x86_mode = svm_guest_x86_mode;
     hvm_funcs.instruction_length = svm_instruction_length;
     hvm_funcs.get_guest_ctrl_reg = svm_get_ctrl_reg;
index a889aaff05fcd9f5c9b41bc9bff788d9536f764d..3996b0f0787af01d1e07292b53bf591fec794f09 100644 (file)
@@ -746,6 +746,7 @@ static void vmx_setup_hvm_funcs(void)
     hvm_funcs.realmode = vmx_realmode;
     hvm_funcs.paging_enabled = vmx_paging_enabled;
     hvm_funcs.long_mode_enabled = vmx_long_mode_enabled;
+    hvm_funcs.pae_enabled = vmx_pae_enabled;
     hvm_funcs.guest_x86_mode = vmx_guest_x86_mode;
     hvm_funcs.instruction_length = vmx_instruction_length;
     hvm_funcs.get_guest_ctrl_reg = vmx_get_ctrl_reg;
index 4ff1ebd445d69b437e186b55001128efde4517e6..fa530c06ca52cc65259b658e1d61ba2761f8f5d8 100644 (file)
@@ -2343,7 +2343,7 @@ void sh_update_paging_modes(struct vcpu *v)
             }
             else
 #endif
-                if ( hvm_get_guest_ctrl_reg(v, 4) & X86_CR4_PAE )
+                if ( hvm_pae_enabled(v) )
                 {
 #if CONFIG_PAGING_LEVELS >= 3
                     // 32-bit PAE mode guest...
index cb573e5d9c1617887c737447cca7c7697a96a7a1..5f1fa73efec3d21d71e69c9bebfa68070886a5bd 100644 (file)
@@ -57,6 +57,7 @@ struct hvm_function_table {
     int (*realmode)(struct vcpu *v);
     int (*paging_enabled)(struct vcpu *v);
     int (*long_mode_enabled)(struct vcpu *v);
+    int (*pae_enabled)(struct vcpu *v);
     int (*guest_x86_mode)(struct vcpu *v);
     int (*instruction_length)(struct vcpu *v);
     unsigned long (*get_guest_ctrl_reg)(struct vcpu *v, unsigned int num);
@@ -146,6 +147,12 @@ hvm_long_mode_enabled(struct vcpu *v)
     return hvm_funcs.long_mode_enabled(v);
 }
 
+ static inline int
+hvm_pae_enabled(struct vcpu *v)
+{
+    return hvm_funcs.pae_enabled(v);
+}
+
 static inline int
 hvm_guest_x86_mode(struct vcpu *v)
 {
index 524411be349fc84bdc9004b85eeccb0896beed9b..02097010c1585f214a621f1c5ccd87c8189976e4 100644 (file)
@@ -39,6 +39,9 @@ enum {
 #define VMX_LONG_GUEST(ed)    \
   (test_bit(VMX_CPU_STATE_LMA_ENABLED, &ed->arch.hvm_vmx.cpu_state))
 
+#define VMX_PAE_GUEST(ed)       \
+  (test_bit(VMX_CPU_STATE_PAE_ENABLED, &ed->arch.hvm_vmx.cpu_state))
+
 struct vmcs_struct {
     u32 vmcs_revision_id;
     unsigned char data [0]; /* vmcs size is read from MSR */
index a60c4523af1dc3d71a61d9f2955e784ca3840121..a77b4d529a286ed1d797b19448e45f9cfdb94a27 100644 (file)
@@ -418,6 +418,12 @@ static inline int vmx_long_mode_enabled(struct vcpu *v)
     return VMX_LONG_GUEST(current);
 }
 
+static inline int vmx_pae_enabled(struct vcpu *v)
+{
+    ASSERT(v == current);
+    return VMX_PAE_GUEST(current);
+}
+
 /* Works only for vcpu == current */
 static inline int vmx_realmode(struct vcpu *v)
 {